#!/usr/bin/env python

"""
 This source file is part of the Swift.org open source project

 Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors
 Licensed under Apache License v2.0 with Runtime Library Exception

 See http://swift.org/LICENSE.txt for license information
 See http://swift.org/CONTRIBUTORS.txt for Swift project authors

 -------------------------------------------------------------------------
"""

from __future__ import print_function

import argparse
from distutils import dir_util
from distutils import file_util
import json
import os
import platform
import re
import shutil
import subprocess
from helpers import note, error, symlink_force, mkdir_p, call, call_output

g_macos_deployment_target = '10.15'

if platform.system() == 'Darwin':
    g_shared_lib_ext = ".dylib"
else:
    g_shared_lib_ext = ".so"

def main():
    parser = argparse.ArgumentParser(description="""
        This script will build a bootstrapped copy of the Swift Package Manager, and optionally perform extra
        actions like installing the result (with 'install') to a location ('--prefix').
        """)
    subparsers = parser.add_subparsers(dest='command')

    # clean
    parser_clean = subparsers.add_parser("clean", help="cleans build artifacts")
    parser_clean.set_defaults(func=clean)
    add_global_args(parser_clean)

    # build
    parser_build = subparsers.add_parser("build", help="builds SwiftPM and runtime libraries")
    parser_build.set_defaults(func=build)
    add_build_args(parser_build)

    # test
    parser_test = subparsers.add_parser("test", help="builds and tests SwiftPM")
    parser_test.set_defaults(func=test)
    add_test_args(parser_test)

    # install
    parser_install = subparsers.add_parser("install", help="builds and installs SwiftPM and runtime libraries")
    parser_install.set_defaults(func=install)
    add_build_args(parser_install)

    args = parser.parse_args()
    args.func = args.func or build
    args.func(args)

# -----------------------------------------------------------
# Argument parsing
# -----------------------------------------------------------

def add_global_args(parser):
    """Configures the parser with the arguments necessary for all actions."""
    parser.add_argument(
        "--build-dir",
        help="path where products will be built [%(default)s]",
        default=".build",
        metavar="PATH")
    parser.add_argument(
        "-v", "--verbose",
        action="store_true",
        help="whether to print verbose output")
    parser.add_argument(
        "--reconfigure",
        action="store_true",
        help="whether to always reconfigure cmake")

def add_build_args(parser):
    """Configures the parser with the arguments necessary for build-related actions."""
    add_global_args(parser)
    parser.add_argument(
        "--swiftc-path",
        help="path to the swift compiler",
        metavar="PATH")
    parser.add_argument(
        "--clang-path",
        help="path to the clang compiler",
        metavar="PATH")
    parser.add_argument(
        '--cmake-path',
        metavar='PATH',
        help='path to the cmake binary to use for building')
    parser.add_argument(
        '--ninja-path',
        metavar='PATH',
        help='path to the ninja binary to use for building with CMake')
    parser.add_argument(
        "--dispatch-build-dir",
        help="path to Dispatch build directory")
    parser.add_argument(
        "--foundation-build-dir",
        help="path to Foundation build directory")
    parser.add_argument(
        "--llbuild-build-dir",
        help="path to llbuild build directory")
    parser.add_argument(
        "--llbuild-link-framework",
        action="store_true",
        help="whether to link to the llbuild framework")
    parser.add_argument(
        "--release",
        action="store_true",
        help="enables building SwiftPM in release mode")
    parser.add_argument(
        "--libswiftpm-install-dir",
        metavar='PATH',
        help="where to install libSwiftPM")
    parser.add_argument(
        "--prefix",
        dest="install_prefixes",
        nargs='*',
        help="paths (relative to the project root) where to install build products [%(default)s]",
        default=["/tmp/swiftpm"],
        metavar="PATHS")

def add_test_args(parser):
    """Configures the parser with the arguments necessary for the test action."""
    add_build_args(parser)
    parser.add_argument(
        "--parallel",
        action="store_true",
        help="whether to run tests in parallel",
        default=True)
    parser.add_argument(
        "--filter",
        action="append",
        help="filter to apply on which tests to run",
        default=[])

def parse_global_args(args):
    """Parses and cleans arguments necessary for all actions."""
    args.build_dir = os.path.abspath(args.build_dir)
    args.project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
    args.tsc_source_dir = os.path.join(args.project_root, "swift-tools-support-core")
    args.yams_source_dir = os.path.join(args.project_root, "..", "yams")
    args.swift_driver_source_dir = os.path.join(args.project_root, "..", "swift-driver")
    args.source_root = os.path.join(args.project_root, "Sources")

    if platform.system() == 'Darwin':
        args.sysroot = call_output(["xcrun", "--sdk", "macosx", "--show-sdk-path"], verbose=args.verbose)
    else:
        args.sysroot = None

def parse_build_args(args):
    """Parses and cleans arguments necessary for build-related actions."""
    parse_global_args(args)

    if args.dispatch_build_dir:
        args.dispatch_build_dir = os.path.abspath(args.dispatch_build_dir)

    if args.foundation_build_dir:
        args.foundation_build_dir = os.path.abspath(args.foundation_build_dir)

    if args.llbuild_build_dir:
        args.llbuild_build_dir = os.path.abspath(args.llbuild_build_dir)

    args.swiftc_path = get_swiftc_path(args)
    args.clang_path = get_clang_path(args)
    args.cmake_path = get_cmake_path(args)
    args.ninja_path = get_ninja_path(args)
    args.target_dir = os.path.join(args.build_dir, get_build_target(args))
    args.bootstrap_dir = os.path.join(args.target_dir, "bootstrap")
    args.conf = 'release' if args.release else 'debug'
    args.bin_dir = os.path.join(args.target_dir, args.conf)

def parse_test_args(args):
    """Parses and cleans arguments necessary for the test action."""
    parse_build_args(args)

def get_swiftc_path(args):
    """Returns the path to the Swift compiler."""
    if args.swiftc_path:
        swiftc_path = os.path.abspath(args.swiftc_path)
    elif os.getenv("SWIFT_EXEC"):
        swiftc_path = os.path.realpath(os.getenv("SWIFT_EXEC"))
    elif platform.system() == 'Darwin':
        swiftc_path = call_output(
            ["xcrun", "--find", "swiftc"],
            stderr=subprocess.PIPE,
            verbose=args.verbose
        )
    else:
        swiftc_path = call_output(["which", "swiftc"], verbose=args.verbose)

    if os.path.basename(swiftc_path) == 'swift':
        swiftc_path = swiftc_path + 'c'

    if os.path.exists(swiftc_path):
        return swiftc_path
    error("unable to find swiftc at %s" % swiftc_path)

def get_clang_path(args):
    """Returns the path to the Clang compiler."""
    if args.clang_path:
        return os.path.abspath(args.clang_path)
    elif platform.system() == 'Darwin':
        return call_output(
            ["xcrun", "--find", "clang"],
            stderr=subprocess.PIPE,
            verbose=args.verbose
        )
    else:
        return call_output(["which", "clang"], verbose=args.verbose)

def get_cmake_path(args):
    """Returns the path to CMake."""
    if args.cmake_path:
        return os.path.abspath(args.cmake_path)
    elif platform.system() == 'Darwin':
        return call_output(
            ["xcrun", "--find", "cmake"],
            stderr=subprocess.PIPE,
            verbose=args.verbose
        )
    else:
        return call_output(["which", "cmake"], verbose=args.verbose)

def get_ninja_path(args):
    """Returns the path to Ninja."""
    if args.ninja_path:
        return os.path.abspath(args.ninja_path)
    elif platform.system() == 'Darwin':
        return call_output(
            ["xcrun", "--find", "ninja"],
            stderr=subprocess.PIPE,
            verbose=args.verbose
        )
    else:
        return call_output(["which", "ninja"], verbose=args.verbose)

def get_build_target(args):
    """Returns the target-triple of the current machine."""
    try:
        target_info_json = subprocess.check_output([args.swiftc_path, '-print-target-info'], stderr=subprocess.PIPE, universal_newlines=True).strip()
        args.target_info = json.loads(target_info_json)
        return args.target_info["target"]["unversionedTriple"]
    except Exception as e:
        # Temporary fallback for Darwin.
        if platform.system() == 'Darwin':
            return 'x86_64-apple-macosx'
        else:
            error(str(e))

# -----------------------------------------------------------
# Actions
# -----------------------------------------------------------

def clean(args):
    """Cleans the build artifacts."""
    note("Cleaning")
    parse_global_args(args)

    call(["rm", "-rf", args.build_dir], verbose=args.verbose)

def build(args):
    """Builds SwiftPM using a two-step process: first using CMake, then with itself."""
    parse_build_args(args)

    # Build llbuild if its build path is not passed in.
    if not args.llbuild_build_dir:
        build_llbuild(args)

    build_tsc(args)
    build_yams(args)
    build_swift_driver(args)
    build_swiftpm_with_cmake(args)
    build_swiftpm_with_swiftpm(args,integrated_swift_driver=False)

def test(args):
    """Builds SwiftPM, then tests itself."""
    build(args)

    note("Testing")
    parse_test_args(args)
    cmd = [os.path.join(args.bin_dir, "swift-test")]
    cmd.append("--enable-test-discovery")
    if args.parallel:
        cmd.append("--parallel")
    for arg in args.filter:
        cmd.extend(["--filter", arg])

    # Test TSC.
    call_swiftpm(args, cmd, args.tsc_source_dir)

    # Test SwiftPM.
    call_swiftpm(args, cmd)

    # Build SwiftPM with the integrated driver.
    note("Bootstrap with the integrated Swift driver")
    build_swiftpm_with_swiftpm(args,integrated_swift_driver=True)

    # Test SwiftPM with the integrated driver. Only the build and
    # functional tests are interesting.
    integratedDriverCmd = cmd
    integratedDriverCmd.append("--use-integrated-swift-driver")
    if args.filter:
        integratedDriverCmd.append("--filter")
        integratedDriverCmd.append("BuildTests;FunctionalTests")
    call_swiftpm(args, integratedDriverCmd)

def install(args):
    """Builds SwiftPM, then installs its build products."""
    build(args)

    # Install swiftpm content in all of the passed prefixes.
    for prefix in args.install_prefixes:
        install_swiftpm(prefix, args)

    # Install libSwiftPM if an install directory was provided.
    if args.libswiftpm_install_dir:
        dest = args.libswiftpm_install_dir

        # FIXME: Don't hardcode the suffix.
        install_binary(args, "libSwiftPM.dylib", dest)

        libswiftpm_modules = [
            "TSCLibc", "TSCBasic",
            "TSCUtility", "SourceControl",
            "SPMLLBuild", "LLBuildManifest",
            "PackageModel", "PackageLoading",
            "PackageGraph", "SPMBuildCore", "Build",
            "Xcodeproj", "Workspace"
        ]

        # Install the swiftmodule and swiftdoc files.
        for module in libswiftpm_modules:
            install_binary(args, module + ".swiftmodule", dest)
            install_binary(args, module + ".swiftdoc", dest)

        # Install the C headers.
        tscclibc_include_dir = os.path.join(args.tsc_source_dir, "Sources/TSCclibc/include")
        tscclibc_include_dir_dest = os.path.join(dest, "TSCclibc")
        dir_util.copy_tree(tscclibc_include_dir, tscclibc_include_dir_dest)

def install_swiftpm(prefix, args):
    # Install swiftpm binaries.
    for binary in ["swift-build", "swift-test", "swift-run", "swift-package"]:
        dest = os.path.join(prefix, "bin")
        install_binary(args, binary, dest)

    if platform.system() == 'Darwin':
        dest = os.path.join(prefix, "libexec", "swift", "pm")
        install_binary(args, "swiftpm-xctest-helper", dest)

    # Install PackageDescription runtime libraries.
    runtime_lib_dest = os.path.join(prefix, "lib", "swift", "pm")
    runtime_lib_src = os.path.join(args.bootstrap_dir, "pm")

    for runtime in ["4", "4_2"]:
        files_to_install = ["libPackageDescription" + g_shared_lib_ext]
        if platform.system() == 'Darwin':
            files_to_install.append("PackageDescription.swiftinterface")
        else:
            files_to_install.append("PackageDescription.swiftmodule")
            files_to_install.append("PackageDescription.swiftdoc")

        for file in files_to_install:
            src = os.path.join(runtime_lib_src, runtime, file)
            dest = os.path.join(runtime_lib_dest, runtime, file)
            mkdir_p(os.path.dirname(dest))

            note("Installing %s to %s" % (src, dest))

            file_util.copy_file(src, dest, update=1)


def install_binary(args, binary, dest_dir):
    src = os.path.join(args.bin_dir, binary)
    dest = os.path.join(dest_dir, binary)

    note("Installing %s to %s" % (src, dest))

    mkdir_p(os.path.dirname(dest))
    file_util.copy_file(src, dest, update=1)

# -----------------------------------------------------------
# Build functions
# -----------------------------------------------------------

def build_with_cmake(args, cmake_args, source_path, build_dir):
    """Runs CMake if needed, then builds with Ninja."""
    cache_path = os.path.join(build_dir, "CMakeCache.txt")
    if args.reconfigure or not os.path.isfile(cache_path) or not args.swiftc_path in open(cache_path).read():
        swift_flags = ""
        if args.sysroot:
            swift_flags = "-sdk %s" % args.sysroot

        cmd = [
            args.cmake_path, "-G", "Ninja",
            "-DCMAKE_MAKE_PROGRAM=%s" % args.ninja_path,
            "-DCMAKE_BUILD_TYPE:=Debug",
            "-DCMAKE_Swift_FLAGS=" + swift_flags,
            "-DCMAKE_Swift_COMPILER:=%s" % (args.swiftc_path),
        ] + cmake_args + [source_path]

        if args.verbose:
            print(' '.join(cmd))

        mkdir_p(build_dir)
        call(cmd, cwd=build_dir, verbose=True)

    # Build.
    ninja_cmd = [args.ninja_path]

    if args.verbose:
        ninja_cmd.append("-v")

    call(ninja_cmd, cwd=build_dir, verbose=args.verbose)

def build_llbuild(args):
    """Builds LLBuild using CMake."""
    note("Building llbuild")

    # Set where we are going to build llbuild for future steps to find it
    args.llbuild_build_dir = os.path.join(args.target_dir, "llbuild")

    api_dir = os.path.join(args.llbuild_build_dir, ".cmake/api/v1/query")
    mkdir_p(api_dir)
    call(["touch", "codemodel-v2"], cwd=api_dir, verbose=args.verbose)

    flags = [
        "-DCMAKE_C_COMPILER:=clang",
        "-DCMAKE_CXX_COMPILER:=clang++",
        "-DLLBUILD_SUPPORT_BINDINGS:=Swift",
    ]

    if args.sysroot:
        flags.append("-DSQLite3_INCLUDE_DIR=%s/usr/include" % args.sysroot)

    llbuild_source_dir = get_llbuild_source_path(args)
    build_with_cmake(args, flags, llbuild_source_dir, args.llbuild_build_dir)

def build_tsc(args):
    note("Building TSC")
    args.tsc_build_dir = os.path.join(args.target_dir, "tsc")

    cmake_flags = []
    if platform.system() == 'Darwin':
        cmake_flags.append("-DCMAKE_C_FLAGS=-target x86_64-apple-macosx%s" % g_macos_deployment_target)
        cmake_flags.append("-DCMAKE_OSX_DEPLOYMENT_TARGET=%s" % g_macos_deployment_target)

    build_with_cmake(args, cmake_flags, args.tsc_source_dir, args.tsc_build_dir)

def build_yams(args):
    note("Building Yams")
    args.yams_build_dir = os.path.join(args.target_dir, "yams")

    cmake_flags = []
    if platform.system() == 'Darwin':
        cmake_flags.append("-DCMAKE_C_FLAGS=-target x86_64-apple-macosx%s" % g_macos_deployment_target)
        cmake_flags.append("-DCMAKE_OSX_DEPLOYMENT_TARGET=%s" % g_macos_deployment_target)
    else:
        if args.dispatch_build_dir:
            cmake_flags.append(get_dispatch_cmake_arg(args))

        if args.foundation_build_dir:
            cmake_flags.append(get_foundation_cmake_arg(args))

    build_with_cmake(args, cmake_flags, args.yams_source_dir, args.yams_build_dir)

def build_swift_driver(args):
    note("Building SwiftDriver")
    args.swift_driver_build_dir = os.path.join(args.target_dir, "swift-driver")

    cmake_flags = [
        get_llbuild_cmake_arg(args),
        "-DTSC_DIR=" + os.path.join(args.tsc_build_dir, "cmake/modules"),
        "-DYams_DIR=" + os.path.join(args.yams_build_dir, "cmake/modules"),
    ]
    if platform.system() == 'Darwin':
        cmake_flags.append("-DCMAKE_C_FLAGS=-target x86_64-apple-macosx%s" % g_macos_deployment_target)
        cmake_flags.append("-DCMAKE_OSX_DEPLOYMENT_TARGET=%s" % g_macos_deployment_target)

    build_with_cmake(args, cmake_flags, args.swift_driver_source_dir, args.swift_driver_build_dir)

def add_rpath_for_cmake_build(args, rpath):
    "Adds the given rpath to the CMake-built swift-build"
    swift_build = os.path.join(args.bootstrap_dir, "bin/swift-build")
    add_rpath_cmd = ["install_name_tool", "-add_rpath", rpath, swift_build]
    note(' '.join(add_rpath_cmd))
    subprocess.call(add_rpath_cmd, stderr=subprocess.PIPE)

def build_swiftpm_with_cmake(args):
    """Builds SwiftPM using CMake."""
    note("Building SwiftPM (with CMake)")

    cmake_flags = [
        get_llbuild_cmake_arg(args),
        "-DTSC_DIR=" + os.path.join(args.tsc_build_dir, "cmake/modules"),
        "-DYams_DIR=" + os.path.join(args.yams_build_dir, "cmake/modules"),
        "-DSwiftDriver_DIR=" + os.path.join(args.swift_driver_build_dir, "cmake/modules"),
    ]

    if platform.system() == 'Darwin':
        cmake_flags.append("-DCMAKE_C_FLAGS=-target x86_64-apple-macosx%s" % g_macos_deployment_target)
        cmake_flags.append("-DCMAKE_OSX_DEPLOYMENT_TARGET=%s" % g_macos_deployment_target)

    build_with_cmake(args, cmake_flags, args.project_root, args.bootstrap_dir)

    if args.llbuild_link_framework:
        add_rpath_for_cmake_build(args, args.llbuild_build_dir)

    if platform.system() == "Darwin":
        add_rpath_for_cmake_build(args, os.path.join(args.yams_build_dir, "lib"))
        add_rpath_for_cmake_build(args, os.path.join(args.swift_driver_build_dir, "lib"))

def build_swiftpm_with_swiftpm(args, integrated_swift_driver):
    """Builds SwiftPM using the version of SwiftPM built with CMake."""
    note("Building SwiftPM (with swift-build)")

    swiftpm_args = [
        "SWIFT_EXEC=" + args.swiftc_path,
        "SWIFT_DRIVER_SWIFT_EXEC=" + args.swiftc_path,
        "SWIFTPM_PD_LIBS=" + os.path.join(args.bootstrap_dir, "pm"),
        os.path.join(args.bootstrap_dir, "bin/swift-build"),
        "--disable-sandbox",
    ]
    if integrated_swift_driver:
        swiftpm_args.append("--use-integrated-swift-driver")

    call_swiftpm(args, swiftpm_args)

    # Setup symlinks that'll allow using swiftpm from the build directory.
    symlink_force(args.swiftc_path, os.path.join(args.target_dir, args.conf, "swiftc"))
    symlink_force(args.swiftc_path, os.path.join(args.target_dir, args.conf, "swift"))

    lib_dir = os.path.join(args.target_dir, "lib", "swift")

    # Remove old cruft.
    if os.path.isdir(lib_dir):
        shutil.rmtree(lib_dir)

    mkdir_p(lib_dir)

    symlink_force(os.path.join(args.bootstrap_dir, "pm"), os.path.join(lib_dir, "pm"))

def call_swiftpm(args, cmd, cwd=None):
    """Calls a SwiftPM binary with the necessary environment variables and flags."""
    full_cmd = get_swiftpm_env_cmd(args) + cmd + get_swiftpm_flags(args)
    if cwd is None:
        cwd = args.project_root
    call(full_cmd, cwd=cwd, verbose=True)

# -----------------------------------------------------------
# Build-related helper functions
# -----------------------------------------------------------

def get_dispatch_cmake_arg(args):
    """Returns the CMake argument to the Dispatch configuration to use for bulding SwiftPM."""
    dispatch_dir = os.path.join(args.dispatch_build_dir, "cmake/modules")
    return "-Ddispatch_DIR=" + dispatch_dir

def get_foundation_cmake_arg(args):
    """Returns the CMake argument to the Foundation configuration to use for bulding SwiftPM."""
    foundation_dir = os.path.join(args.foundation_build_dir, "cmake/modules")
    return "-DFoundation_DIR=" + foundation_dir

def get_llbuild_cmake_arg(args):
    """Returns the CMake argument to the LLBuild framework/binary to use for bulding SwiftPM."""
    if args.llbuild_link_framework:
        return "-DCMAKE_FIND_FRAMEWORK_EXTRA_LOCATIONS=%s" % args.llbuild_build_dir
    else:
        llbuild_dir = os.path.join(args.llbuild_build_dir, "cmake/modules")
        return "-DLLBuild_DIR=" + llbuild_dir

def get_llbuild_source_path(args):
    """Returns the path to the LLBuild source folder."""
    llbuild_path = os.path.join(args.project_root, "..", "llbuild")
    if os.path.exists(llbuild_path):
        return llbuild_path
    note("clone llbuild next to swiftpm directory; see development docs: https://github.com/apple/swift-package-manager/blob/master/Documentation/Development.md#using-trunk-snapshot")
    error("unable to find llbuild source directory at %s" % llbuild_path)

def get_swiftpm_env_cmd(args):
    """Returns the environment variable command to run SwiftPM binaries."""
    env_cmd = ["env"]

    if args.sysroot:
        env_cmd.append("SDKROOT=%s" % args.sysroot)

    if args.llbuild_link_framework:
        env_cmd.append("SWIFTPM_LLBUILD_FWK=1")
    env_cmd.append("SWIFTCI_USE_LOCAL_DEPS=1")
    env_cmd.append("SWIFTPM_MACOS_DEPLOYMENT_TARGET=%s" % g_macos_deployment_target)

    libs_joined = ":".join([
        os.path.join(args.bootstrap_dir, "lib"),
        os.path.join(args.tsc_build_dir, "lib"),
        os.path.join(args.llbuild_build_dir, "lib"),
        os.path.join(args.yams_build_dir, "lib"),
        os.path.join(args.swift_driver_build_dir, "lib"),
    ])

    if platform.system() == 'Darwin':
        env_cmd.append("DYLD_LIBRARY_PATH=%s" % libs_joined)
    else:
        env_cmd.append("LD_LIBRARY_PATH=%s" % libs_joined)

    return env_cmd

def get_swiftpm_flags(args):
    """Returns the flags to run SwiftPM binaries."""
    build_flags = [
        "--build-path", args.build_dir,
    ]

    if args.release:
        build_flags.extend([
            "--configuration", "release",
        ])

    if args.verbose:
        build_flags.append("--verbose")

    if args.llbuild_link_framework:
        build_flags.extend([
            "-Xswiftc", "-F" + args.llbuild_build_dir,
            "-Xlinker", "-F" + args.llbuild_build_dir,

            # For LLBuild in Xcode.
            "-Xlinker", "-rpath",
            "-Xlinker", "@executable_path/../../../../../SharedFrameworks",

            # For LLBuild in CLT.
            "-Xlinker", "-rpath",
            "-Xlinker", "@executable_path/../lib/swift/pm/llbuild",
        ])

    # Add a relative rpath to find Swift libraries in toolchains.
    # On non-Darwin platforms, a relative rpath is necessary because Swift
    # libraries are not part of the OS.
    # On Darwin platforms, a relative rpath is necessary for experimental
    # toolchains that include libraries not part of the OS (e.g. PythonKit or
    # TensorFlow).
    if platform.system() == "Darwin":
        swift_library_rpath_prefix = "@executable_path/../"
    elif platform.system() == 'Linux':
        # `$ORIGIN` is an ELF construct.
        swift_library_rpath_prefix = "$ORIGIN/../"
    platform_path = None
    for path in args.target_info["paths"]["runtimeLibraryPaths"]:
        platform_path = re.search(r"(lib/swift/[^/]+)$", path)
        if platform_path:
            build_flags.extend(
                [
                    "-Xlinker",
                    "-rpath",
                    "-Xlinker",
                    swift_library_rpath_prefix + platform_path.group(1),
                ]
            )
            break

    if not platform_path:
        error(
            "the command `%s -print-target-info` didn't return a valid runtime library path"
            % args.swiftc_path
        )

    # Don't use GNU strerror_r on Android.
    if 'ANDROID_DATA' in os.environ:
        build_flags.extend(["-Xswiftc", "-Xcc", "-Xswiftc", "-U_GNU_SOURCE"])

    # On ELF platforms, remove the host toolchain's stdlib absolute rpath from
    # installed executables and shared libraries.
    if platform.system() != "Darwin" and args.command == 'install':
        build_flags.extend(["-Xswiftc", "-no-toolchain-stdlib-rpath"])

    return build_flags

if __name__ == '__main__':
    main()
